package IC.Parser;
import IC.Parser.Token;
%%

%cup
%class Lexer
%public
%function next_token
%type Token
%line
%scanerror LexicalError
%state ONELINECOMMENT
%state COMMENT
%state COMMENT_STAR
%state STR
%state SLASH
%{
	private String temp;
%}
%eofval{
	if (yystate() == STR) { 
		throw new LexicalError("Lexical error: Unterminated String at line "+yyline);
	}
	if (yystate() == COMMENT ) {
		throw new LexicalError("Lexical error: Unterminated Comment at line "+yyline);
	
	}
  	return new Token(sym.EOF, yyline,"EOF",null);
%eofval}

ALPHA = [A-Za-z_] 
DIGIT = [0-9]
ALPHA_NUMERIC = {ALPHA}|{DIGIT}
LOWER_CASE= [a-z]
IDENT = {LOWER_CASE}({ALPHA_NUMERIC})*
NUMBER = ({DIGIT})+
CAPITAL = [A-Z]
CLASS_IDEN = {CAPITAL}({ALPHA_NUMERIC})*
BLANKS = [ \n\t\r]
%%

/* one line comment */
<YYINITIAL> "//" {yybegin(ONELINECOMMENT);}
<ONELINECOMMENT> [^\n] {}
<ONELINECOMMENT> [\n] {yybegin(YYINITIAL);}

/* longer comment */
<YYINITIAL> "/*" {yybegin(COMMENT);}
<COMMENT> [^*] {}
<COMMENT> [*]+ {yybegin(COMMENT_STAR);}
<COMMENT_STAR> "/" {yybegin(YYINITIAL);}
<COMMENT_STAR> [^/] {yybegin(COMMENT);}

/* strings */
<YYINITIAL> [\"] {yybegin(STR);temp="\"";}

<STR> [\"] {
			temp += "\"";
			yybegin(YYINITIAL);
			return new Token(sym.QUOTE,yyline,"QUOTE",temp);
			}
<STR> "\\" { yybegin(SLASH);}

<SLASH> "t" { temp += "\\t"; yybegin(STR);}
<SLASH> "n" { temp += "\\n"; yybegin(STR);}
<SLASH> "\"" { temp += "\\\""; yybegin(STR);}
<SLASH> "\\" { temp += "\\\\"; yybegin(STR);}
<SLASH> . {throw new LexicalError(yyline,"Bad escape charactar in string: '\\"+yytext()+"'");}
<STR> [\n]  {
				throw  new LexicalError(yyline,"new newline in string");
			}
<STR> .  
			{
			 	if ((yytext().charAt(0) >= 32) && (yytext().charAt(0) <= 126)) {
             		temp += yytext();
             	} else {
             		throw new LexicalError(yyline,"Bad charactar in string: '"+yytext()+"'");
             	}
			}


<YYINITIAL> {BLANKS} {}
<YYINITIAL> "(" { return new Token(sym.LP,yyline,"LP",null); }
<YYINITIAL> ")" { return new Token(sym.RP,yyline,"RP",null); }
<YYINITIAL> "=" { return new Token(sym.ASSIGN,yyline,"ASSIGN",null);}
<YYINITIAL> "boolean" { return new Token(sym.BOOLEAN,yyline,"BOOLEAN",null);}
<YYINITIAL> "break" { return new Token(sym.BREAK,yyline,"BREAK",null);}
<YYINITIAL> "," { return new Token(sym.COMMA,yyline,"COMMA",null);}
<YYINITIAL> "continue" { return new Token(sym.CONTINUE,yyline,"CONTINUE",null);}
<YYINITIAL> "/" { return new Token(sym.DIVIDE,yyline,"DIVIDE",null);}
<YYINITIAL> "." { return new Token(sym.DOT,yyline,"DOT",null);}
<YYINITIAL> "==" { return new Token(sym.EQUAL,yyline,"EQUAL",null);}
<YYINITIAL> "extends" { return new Token(sym.EXTENDS,yyline,"EXTENDS",null);}
<YYINITIAL> "else" { return new Token(sym.ELSE,yyline,"ELSE",null);}
<YYINITIAL> "false" { return new Token(sym.FALSE,yyline,"FALSE",null);}
<YYINITIAL> ">" { return new Token(sym.GT,yyline,"GT",null);}
<YYINITIAL> "<" { return new Token(sym.LT,yyline,"LT",null);}
<YYINITIAL> ">=" { return new Token(sym.GTE,yyline,"GTE",null);}
<YYINITIAL> "if" { return new Token(sym.IF,yyline,"IF",null);}
<YYINITIAL> "int" { return new Token(sym.INT,yyline,"INT",null);}
<YYINITIAL> "&&" { return new Token(sym.LAND,yyline,"LAND",null);}
<YYINITIAL> "[" { return new Token(sym.LB,yyline,"LB",null);}
<YYINITIAL> "{" { return new Token(sym.LCBR,yyline,"LCBR",null);}
<YYINITIAL> "length" { return new Token(sym.LENGTH,yyline,"LENGTH",null);}
<YYINITIAL> "new" { return new Token(sym.NEW,yyline,"NEW",null);}
<YYINITIAL> "!" { return new Token(sym.LNEG,yyline,"LNEG",null);}
<YYINITIAL> "||" { return new Token(sym.LOR,yyline,"LOR",null);}
<YYINITIAL> "<=" { return new Token(sym.LTE,yyline,"LTE",null);}
<YYINITIAL> "-" { return new Token(sym.MINUS,yyline,"MINUS",null);}
<YYINITIAL> "%" { return new Token(sym.MOD,yyline,"MOD",null);}
<YYINITIAL> "*" { return new Token(sym.MULTIPLY,yyline,"MULTIPLY",null);}
<YYINITIAL> "!=" { return new Token(sym.NEQUAL,yyline,"NEQUAL",null);}
<YYINITIAL> "null" { return new Token(sym.NULL,yyline,"NULL",null);}
<YYINITIAL> "+" { return new Token(sym.PLUS,yyline,"PLUS",null);}
<YYINITIAL> "]" { return new Token(sym.RB,yyline,"RB",null);}
<YYINITIAL> "}" { return new Token(sym.RCBR,yyline,"RCBR",null);}
<YYINITIAL> "return" { return new Token(sym.RETURN,yyline,"RETURN",null);}
<YYINITIAL> ";" { return new Token(sym.SEMI,yyline,"SEMI",null);}
<YYINITIAL> "static" { return new Token(sym.STATIC,yyline,"STATIC",null);}
<YYINITIAL> "string" { return new Token(sym.STRING,yyline,"STRING",null);}
<YYINITIAL> "this" { return new Token(sym.THIS,yyline,"THIS",null);}
<YYINITIAL> "true" { return new Token(sym.TRUE,yyline,"TRUE",null);}
<YYINITIAL> "void" { return new Token(sym.VOID,yyline,"VOID",null);}
<YYINITIAL> "while" { return new Token(sym.WHILE,yyline,"WHILE",null);}
<YYINITIAL> "class" {return new Token(sym.CLASS,yyline,"CLASS",null);}
<YYINITIAL> {CLASS_IDEN} {return new Token(sym.CLASS_ID,yyline,"CLASS_ID",yytext());}
<YYINITIAL> {IDENT} {return new Token(sym.ID,yyline,"ID",yytext());}
<YYINITIAL> {NUMBER} { return new Token(sym.INTEGER,yyline,"INTEGER",new Integer(yytext()));}
<YYINITIAL> [^a] { throw new LexicalError(yyline,"Unknown charactar found: "+yytext()+", ASCII: "+(int)yytext().charAt(0));}


